namespace study61 {

  /**
   * Partial --- 让属性变为可选
   * Pick --- 选择某些属性，并使用交叉类型新增属性
   * Omit --- 排除某些属性，并使用交叉类型新增属性
   * Record --- 生成键值对
   * Readonly --- 让属性变为只读
   */
  
  // 1. Partial --- 让属性变为可选
  type Person = {
    name: string,
    age: number
  }

  type Person2 = Partial<Person>

  type Person3 = {
    name: string,
    age: number,
    text: string,
    address: string
  }

  // 2. Pick
  // 要求1：使用 Pick 抽取需要的属性（name,age)，并且使用交叉类型新增e属性
  type Person4 = Pick<Person3, 'name' | 'age'> & {
    e: string
  }

  let obj: Person4 = {
    age: 20,
    name: 'John',
    e: 'test'
  }

  // Omit ---排除某些属性，并使用交叉类型新增sex属性
  interface User {
    id: number,
    name: string,
    age: number,
    email: string
  }

  type OmitUser = Omit<User, 'email'> & {
    sex: string
  }

  let oUserData: OmitUser = {
    id: 1,
    name: 'John',
    age: 20,
    sex: '男'
  }

  // 要求2：让新类型的属性变为可选, partial<>
  type Person5 = Partial<Pick<Person3, 'name' | 'age'> & {
    e: string
  }>

  let obj2: Person5 = {
    age: 20,
    name: 'John',
    e: 'test'
  }




  // 要求3：让新类型的属性变为可选, Readonly<>
  type Person6 = Readonly<Pick<Person3, 'name' | 'age'> & {
    e: string
  }>

  // Record --- 生成键值对

  type Persona = {
    name: string,
    age: number,
    text: string
  }

  type K = 'a' | 'b' | 'c'

  type newObj = Record<K, Persona>

  // 等同于
  //   type newObj = {
  //     a: Persona;
  //     b: Persona;
  //     c: Persona;
  // }

  class Student {
    constructor(
      public name: string,
      public age: number
    ) {}
  }

  // 键：使用 Persona 属性作为键值  值：传入 Student 对象 按照这个需求声明一个对象类型
  type newObj2 = Record<keyof Persona, Student>
  let stuData: newObj2 = {
    age: new Student('John', 20),
    name: new Student('Mary', 21),
    text: new Student('Tom', 22)
  }
}